﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Narwhunderful.Aphelia.Framework.Graphics
{

    public class Camera2D : UpdatableComponent
    {

        static Viewport _originalViewport;

        SpriteBatch _spriteBatch;
        public SpriteBatch SpriteBatch
        {
            get
            {
                return _spriteBatch;
            }
            set
            {
                _spriteBatch = value;
            }
        }

        BasicEffect _basicEffect;
        public BasicEffect BasicEffect
        {
            get
            {
                return _basicEffect;
            }
            protected set
            {
                _basicEffect = value;
            }
        }

        RasterizerState _rasterizerState = new RasterizerState();
        public RasterizerState RasterizerState
        {
            get
            {
                return _rasterizerState;
            }
            set
            {
                _rasterizerState = value;
            }
        }

        Vector2 _location = Vector2.Zero;
        public Vector2 Location
        {
            get
            {
                return _location;
            }
            set
            {
                _location = value;
                base.NeedsUpdate = true;
            }
        }

        float _rotation = 0.0f;
        public float Rotation
        {
            get
            {
                return _rotation;
            }
            set
            {
                _rotation = value;
                base.NeedsUpdate = true;
            }
        }

        Vector2 _origin = Vector2.Zero;
        public Vector2 Origin
        {
            get
            {
                return _origin;
            }
            set
            {
                _origin = value;
            }
        }

        float _zoom = 1.0f;
        public float Zoom
        {
            get
            {
                return _zoom;
            }
            set
            {
                _zoom = value;
                base.NeedsUpdate = true;
            }
        }

        public Camera2D(Game game)
            : base(game)
        {
            _originalViewport = base.Game.GraphicsDevice.Viewport;
            _rasterizerState.ScissorTestEnable = true;
            _spriteBatch = new SpriteBatch(game.GraphicsDevice);
            _basicEffect = new BasicEffect(game.GraphicsDevice);
            _basicEffect.TextureEnabled = true;
            _basicEffect.VertexColorEnabled = true;
            _origin = new Vector2(_originalViewport.Width * 0.5f, _originalViewport.Height * 0.5f);
        }

        #region IUpdatableComponent

        protected override void InternalUpdate(GameTime gameTime)
        {
            UpdateEffect(gameTime);
            UpdateWorldTransform(gameTime);
            UpdateViewTransform(gameTime);
            UpdateProjectionTransform(gameTime);
        }

        protected internal virtual void UpdateWorldTransform(GameTime gameTime)
        {
            _basicEffect.World = Matrix.Identity
                ;
        }

        protected internal virtual void UpdateViewTransform(GameTime gameTime)
        {
            _basicEffect.View = Matrix.Identity
                * Matrix.CreateTranslation(new Vector3(_location, 0.0f))
                * Matrix.CreateScale(new Vector3(_zoom, _zoom, 0.0f))
                * Matrix.CreateRotationZ(_rotation)
                //* Matrix.CreateTranslation(new Vector3(-_origin, 0.0f));
                 ;
        }

        protected internal virtual void UpdateProjectionTransform(GameTime gameTime)
        {
            _basicEffect.Projection = Matrix.Identity
                * Matrix.CreateTranslation(-0.5f, -0.5f, 0)
                * Matrix.CreateOrthographicOffCenter(_originalViewport.X, _originalViewport.Width, _originalViewport.Height, _originalViewport.Y, _originalViewport.MinDepth, _originalViewport.MaxDepth)
                ;
        }


        protected internal virtual void UpdateEffect(GameTime gameTime)
        {
        }

        #endregion

        public virtual void Reset()
        {
            _location = Vector2.Zero;
            _zoom = 1.0f;
            _rotation = 0.0f;
            _origin = new Vector2(_originalViewport.Width * 0.5f, _originalViewport.Height * 0.5f);
            base.NeedsUpdate = true;
        }

    }

}
